"use strict";

var zookeeper = require('node-zookeeper-client');
var amqp = require('amqplib/callback_api');
var msgpack = require('msgpack');

// zk
var __zkNode = '/myrpc/server/currid';
// var __zkConfig = 'localhost:2181';
var __zkConfig = '192.168.102.142:2181';
var __zkBaseId = '1';

// mq
// var __rabbitmqConfig = 'amqp://localhost';
var __rabbitmqConfig = 'amqp://wzq:r@192.168.102.142';
// var __qRequest = 'request_to_{type}';
// var __qReply = 'reply_to_{appId}';
var __msgpack = true; // use msgpack


/**
 * 
 */
function RpcBase() {}
module.exports = RpcBase;

RpcBase.prototype.init = function(cb) {
	var self = this;
	__prepareZk(this, function(obj, zk, id, mqconn) {
		self.__id = id;
		self.__zk = zk;
		self.__mqconn = mqconn;
		self.__msgpack = __msgpack;
		cb && cb();
	});
};

// input object
// return Buffer
RpcBase.prototype.pack = function(msg) {
	if (this.__msgpack) {
		return msgpack.pack(msg);
	} else {
		var str = JSON.stringify(msg);
		return new Buffer(str);
	}
};

// input Buffer
// return object
RpcBase.prototype.unpack = function(msg) {
	var obj;
	if (this.__msgpack) {
		obj = msgpack.unpack(msg);
	} else {
		var str = msg.toString();
		obj = JSON.parse(str);
	}

	if (typeof(obj) === 'string')
		obj = JSON.parse(obj);
	return obj;
};

function __prepareZk(obj, cb) {
	// console.log('prepareZk');
	var zk = zookeeper.createClient(__zkConfig);
	zk.connect();
	zk.once('connected', function() {
		// console.log('zk connected');
		__getNextId(obj, zk, cb);
	});
}


/** get id from zookeeper */
function __getNextId(obj, zk, cb) {
	// console.log('__getNextId');
	if (obj.__id) {
		return __prepareMq(obj, zk, obj.__id, cb);
	}

	// if exists read and save , not exist mkdir and save
	function getId() {
		zk.getData(__zkNode, null, function(err, data, stat) {
			// console.log('getData node %s', __zkNode);
			if (err) throw err;
			var nextId = parseInt(data) + 1;
			zk.setData(__zkNode, new Buffer(nextId + ''), -1, function(err, stat) {
				if (err) throw err;
				__prepareMq(obj, zk, nextId, cb);
			});
		});
	}

	function firstSetId() {
		zk.mkdirp(__zkNode, new Buffer(__zkBaseId + ''), function(err, path) {
			// console.log('create node %s', __zkNode);
			if (err) throw err;
			__prepareMq(obj, zk, parseInt(__zkBaseId), cb);
		});
	}


	zk.exists(__zkNode, function(err, stat) {
		if (err) throw err;
		if (stat) { // if exists read and save
			getId();
		} else { // not exist mkdir and save
			firstSetId();
		}
	});
}


function __prepareMq(obj, zk, id, cb) {
	// console.log('__prepareMq');
	amqp.connect(__rabbitmqConfig, function(err, conn) {
		if (err) throw err;
		// console.log('mq connected');
		cb(obj, zk, id, conn);
	});
}